package cn.liuxb.spa;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import cn.liuxb.spa.SpaHandler.SpaContext;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.util.CharsetUtil;
import lombok.extern.log4j.Log4j2;

@Component
@Log4j2
@Sharable
public class NettyHttpHandler extends ChannelInboundHandlerAdapter {
	ScheduledExecutorService timeoutExecutor = Executors.newScheduledThreadPool(5);
	ExecutorService bizExecutor = Executors.newFixedThreadPool(10);
	
	@Autowired
	SpaHandler spaHandler;

	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		log.info("链接建立,客户端地址:" + ctx.channel().remoteAddress());
		super.channelActive(ctx);
	}

	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		log.info("链接断开,客户端地址:" + ctx.channel().remoteAddress());
		super.channelInactive(ctx);
	}

	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
		if (!(msg instanceof FullHttpRequest)) {
			sendResponse(ctx, "未知请求!", HttpResponseStatus.BAD_REQUEST);
			return;
		}

		FullHttpRequest httpRequest = (FullHttpRequest) msg;
		try {
			String uri = httpRequest.uri(); // 获取路径
			HttpMethod method = httpRequest.method();// 获取请求方法
			log.info("接收到" + method + "请求:" + uri);
			// 如果不是这个路径，就直接返回错误
			if (!"/pay".equalsIgnoreCase(uri)) {
				sendResponse(ctx, "请求的URI不存在:" + uri, HttpResponseStatus.NOT_FOUND);
				return;
			}
			// 如果是GET请求
			if (!HttpMethod.GET.equals(method) && !HttpMethod.POST.equals(method)) {
				sendResponse(ctx, "不支持的请求方式:" + method, HttpResponseStatus.METHOD_NOT_ALLOWED);
				return;
			}
		} catch (Exception e) {
			log.info("处理请求失败!", e);
		} finally {
			// 释放请求
//			httpRequest.release();
		}
		
		bizExecutor.execute(()->bizHandle(ctx, httpRequest));
	}

	private String getBody(FullHttpRequest request) {
		ByteBuf buf = request.content();
		return buf.toString(CharsetUtil.UTF_8);
	}

	private void bizHandle(ChannelHandlerContext ctx, FullHttpRequest httpRequest) {
		try {
			SpaContext sc = new SpaContext().reqStr(getBody(httpRequest)).reqTimeMs(System.currentTimeMillis()).ctx(ctx);
			spaHandler.onRequest(sc);
		} catch (Exception e) {
			sendResponse(ctx,"服务异常:"+e.getMessage(),HttpResponseStatus.INTERNAL_SERVER_ERROR);
		}finally {
			httpRequest.release();
		}
	}

	public void sendResponse(ChannelHandlerContext sc, String respStr, HttpResponseStatus status) {
		log.info("发送应答:" + respStr);
		FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status,
				Unpooled.copiedBuffer(respStr, CharsetUtil.UTF_8));
		response.headers().set(HttpHeaderNames.CONTENT_TYPE, "application/json; charset=UTF-8");
		sc.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
	}

}
